const toStr = Object.prototype.toString.call;

class Is {
  /**
   * #### js原始数据类型
   * 总共有7种原始数据类型，分别是：
   * - string 用于表示文本数据。字符串可以通过单引号（' '）、双引号（ " "）或反引号（\` \`）来定义。
   * - number 用于表示数值。JavaScript中的数字可以是整数或浮点数。
   * - boolean 表示逻辑上的真（true）或假（false）。
   * - undefined 表示变量未被赋值时的值。
   * - null 表示空值或没有对象被赋给变量的值。
   * - symbol （ES6新增）：表示独一无二的值，通常用于对象的属性名。
   * - bigint （ES2020新增）：用于表示大于2^53 - 1的整数。
   */
  static PRIMITIVE_TYPES = [
    "string",
    "number",
    "boolean",
    "undefined",
    "null",
    "symbol",
    "bigint",
  ];

  /**
   * 检查给定的值是否可以转换为数字
   * @param value - 需要检查的未知类型值
   * @returns 如果值是字符串且可以转换为数字则返回true，否则返回false
   */
  static isStringNumber(value: unknown): boolean {
    // 首先检查输入值是否为字符串类型
    if (typeof value !== "string") {
      return false;
    }
    // 尝试将字符串转换为数字，并检查结果是否为NaN
    // 如果不是NaN，则表示该字符串可以转换为有效数字
    return !Number.isNaN(Number(value));
  }

  /**
   * 检查输入值是否为字符串形式的布尔值（"true"或"false"）
   * @param value - 需要检查的未知类型值
   * @returns 如果值是字符串"true"或"false"（不区分大小写）则返回true，否则返回false
   */
  static isStringBoolean(value: unknown): boolean {
    // 首先检查输入值是否为字符串类型，如果不是则直接返回false
    if (typeof value !== "string") {
      return false;
    }
    // 将字符串转换为小写，并检查是否包含在["true", "false"]数组中
    return ["true", "false"].includes(value.toLowerCase());
  }

  /**
   * 检查一个值是否是js基本原始的数据类型
   * @param value - 需要检查的值
   * @returns 如果值是基本数据类型则返回true，否则返回false
   */
  static isPrimitive(value: unknown): boolean {
    // 使用typeof操作符检查值的类型，并判断是否在primitiveTypes数组中
    return value === null || this.PRIMITIVE_TYPES.includes(typeof value);
  }

  static isArray(value: unknown): value is Array<unknown> {
    return Array.isArray(value);
  }

  static isObject(value: unknown) {
    return value !== null && typeof value === "object";
  }
  static isString(value: unknown): value is string {
    return typeof value === "string";
  }
}

export default Is;
